/* 
 * Copyright (c) Sergey B. Berezin (s_berezin@cs.msu.su), 2002, 2003.
 *
 * You may freely distribute or modify this source code retaining the 
 * above copyright notice.
 *
 * This software is provided "as-is" and without guarantee or warrantee 
 * of any kind, expressed or implied :)
 */

using System;
using System.Drawing;
using System.Windows.Forms;

using OpenGL;



namespace UVS.UI {

	//	public delegate void SelectHandler(Rectangle selection);

	public class SelectorLayer : UILayer {

		protected bool tracking = false;
		protected int x1,y1,x2,y2;
		//public event SelectHandler Select = new SelectHandler();

		public virtual void OnMouseDown(object sender,MouseEventArgs a) {
			if((a.Button & MouseButtons.Left) != 0) {
				if(!tracking) {
					tracking = true;
					x1 = x2 = a.X;
					y1 = y2 = a.Y;
					//owner.RenderAllLayers(); // Ensure that back buffer is similar to front buffer
				}
			}
		}

		public virtual void OnMouseUp(object sender,MouseEventArgs a) {
			if((a.Button & MouseButtons.Left) != 0) {
				if(tracking) {
					BeginDrawing();
					DrawSelectionRect();
					EndDrawing();
					if(x1 != x2 && y1 != y2) {
						Rectangle selection = new Rectangle();
						if(x1 < x2) {
							selection.X = x1;
							selection.Width = x2 - x1;
						} else {
							selection.X = x2;
							selection.Width = x1 - x2;
						}
						if(y1 < y2) {
							selection.Y = y1;
							selection.Height = y2 - y1;
						} else {
							selection.Y = y2;
							selection.Height = y1 - y2;
						}
						OnSelect(selection);
					}
					tracking = false;
				} 
			}
		}
	
		public void OnMouseMove(object sender,MouseEventArgs a) {
			if(tracking) {
				BeginDrawing();
				DrawSelectionRect();
				x2 = a.X;
				y2 = a.Y;
				DrawSelectionRect();
				EndDrawing();
			}
		}

		public virtual void OnSelect(Rectangle selection) {
			//Select(selection);
		}

		public override void OnControlAttached() {
			Control.MouseDown += new MouseEventHandler(this.OnMouseDown);
			Control.MouseUp += new MouseEventHandler(this.OnMouseUp);
			Control.MouseMove += new MouseEventHandler(this.OnMouseMove);
		}

		public override void OnControlDetached() {
			Control.MouseDown -= new MouseEventHandler(this.OnMouseDown);
			Control.MouseUp -= new MouseEventHandler(this.OnMouseUp);
			Control.MouseMove -= new MouseEventHandler(this.OnMouseMove);
			base.OnControlDetached();
		}

		public override void OnRender() {
			// Nothing to do here
		}

		protected void BeginDrawing() {
			view.Context.MakeCurrent();
			GL.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT);
			GL.glDrawBuffer(GL.GL_FRONT); // Enable drawing to front buffer
			GL.glMatrixMode(GL.GL_PROJECTION);
			GL.glPushMatrix();
			GL.glLoadIdentity();
			GL.glOrtho(0,Width,0,Height,-1,1);
			GL.glMatrixMode(GL.GL_MODELVIEW);
			GL.glPushMatrix();
			GL.glLoadIdentity();
			GL.glDisable(GL.GL_CULL_FACE);
			GL.glEnable(GL.GL_BLEND);
			GL.glBlendFunc(GL.GL_ONE_MINUS_DST_COLOR,GL.GL_ZERO);
			GL.glEnable(GL.GL_LINE_STIPPLE);
			GL.glLineStipple(3,0xAAAA);
			GL.glPolygonMode(GL.GL_FRONT_AND_BACK,GL.GL_LINE);
		}

		protected void DrawSelectionRect() {
			if(x1 != x2 && y1 != y2) {
				GL.glBegin(GL.GL_QUADS);
				GL.glColor3f(1,1,1);
				GL.glVertex2i(x1,Height - y1);
				GL.glVertex2i(x1,Height - y2);
				GL.glVertex2i(x2,Height - y2);
				GL.glVertex2i(x2,Height - y1);
				GL.glEnd();
			}
		}

		protected void EndDrawing() {
			GL.glMatrixMode(GL.GL_MODELVIEW);
			GL.glPopMatrix();
			GL.glMatrixMode(GL.GL_PROJECTION);
			GL.glPopMatrix();
			GL.glDisable(GL.GL_BLEND);
			GL.glDisable(GL.GL_LINE_STIPPLE);
			GL.glPopAttrib();
			GL.glFlush();
			GL.glDrawBuffer(GL.GL_BACK);
			// owner.Context.SwapBuffers();
		}
	}
}